Pushover Agent.

akil harris 11 years ago
parent
commit
9d9679eec1
2 changed files with 237 additions and 39 deletions
  1. 36 39
      app/models/agents/pushover_agent.rb
  2. 201 0
      spec/models/agents/pushover_agent_spec.rb

+ 36 - 39
app/models/agents/pushover_agent.rb

@@ -1,30 +1,35 @@
1
-
2 1
 module Agents
3 2
   class PushoverAgent < Agent
4 3
     cannot_be_scheduled!
5 4
     cannot_create_events!
6 5
 
6
+    @@api_url = 'https://api.pushover.net/1/messages.json'
7
+
7 8
     description <<-MD
8 9
       The PushoverAgent receives and collects events and sends them via push notification to a user/group.
9 10
 
10
-      You need a Pushover API Token: [https://pushover.net/apps/build](https://pushover.net/apps/build)
11
+      **You need a Pushover API Token:** [https://pushover.net/apps/build](https://pushover.net/apps/build)
12
+      
13
+      **Your event must provide** a `message` or `text` key that will contain the body of the notification. Pushover API has a `512` Character Limit including `title`. `message` will be truncated.
11 14
 
12 15
       * `token`: your application's API token
13 16
       * `user`: the user or group key (not e-mail address).
14 17
       * `expected_receive_period_in_days`:  is maximum number of days that you would expect to pass between events being received by this agent.
15 18
       
16
-      Your event should provide a `message` or `text` key that will contain the body of the notification. Pushover API has a `512` Character Limit including title. 
17
-
18 19
       Your event can provide any of the following optional parameters or you can provide defaults:
19 20
 
20 21
       * `device` - your user's device name to send the message directly to that device, rather than all of the user's devices
21 22
       * `title` or `subject` - your notifications's title
22 23
       * `url` - a supplementary URL to show with your message - `512` Character Limit
23 24
       * `url_title` - a title for your supplementary URL, otherwise just the URL is shown - `100` Character Limit
24
-      * `priority` - send as -1 to always send as a quiet notification, 1 to display as high-priority and bypass the user's quiet hours, or 2 to also require confirmation from the user
25
-      * `timestamp` - a [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time) of your message's date and time to display to the user, rather than the time your message is received by our API
26
-      * `sound` - the name of one of the sounds supported by device clients to override the user's default sound choice
25
+      * `priority` - send as `-1` to always send as a quiet notification, `0` is default, `1` to display as high-priority and bypass the user's quiet hours, or `2` for emergency priority: [Please read Pushover Docs on Emergency Priority](https://pushover.net/api#priority)
26
+      * `sound` - the name of one of the sounds supported by device clients to override the user's default sound choice. [See PushOver docs for sound options.](https://pushover.net/api#sounds)
27
+      * `retry` - Requred for emergency priority - Specifies how often (in seconds) the Pushover servers will send the same notification to the user. Minimum value: `30`
28
+      * `expire` - Requred for emergency priority - Specifies how many seconds your notification will continue to be retried for (every retry seconds). Maximum value: `86400`
29
+
30
+      Your event can also pass along a timestamp parameter:
27 31
 
32
+      * `timestamp` - a [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time) of your message's date and time to display to the user, rather than the time your message is received by the Pushover API.
28 33
 
29 34
     MD
30 35
 
@@ -36,9 +41,10 @@ module Agents
36 41
         'title' => '',
37 42
         'url' => '',
38 43
         'url_title' => '',
39
-        'priority' => '0',
40
-        'timestamp' => '',
44
+        'priority' => 0,
41 45
         'sound' => 'pushover',
46
+        'retry' => 0,
47
+        'expire' => 0,
42 48
         'expected_receive_period_in_days' => '1'
43 49
       }
44 50
     end
@@ -59,40 +65,30 @@ module Agents
59 65
               'message' => message
60 66
             }
61 67
 
62
-            if event.payload['device'] || options['device']
63
-              post_params['device'] = event.payload['device'] || options['device']
64
-            end
65
-
66
-            if event.payload['title'] || options['title']
67
-              post_params['title'] = event.payload['title'] || options['title']
68
-            end
69
-
70
-            if event.payload['url'] || options['url']
71
-              url = (event.payload['url'] || options['url'] || '').to_s
72
-              url = url.slice 0..512
73
-              post_params['url'] = url
74
-            end
75
-
76
-            if event.payload['url_title'] || options['url_title']
77
-              url_title = (event.payload['url_title'] || options['url_title']).to_s
78
-              url_title = url_title.slice 0..100
79
-              post_params['url_title'] = url_title
68
+            post_params['device'] = event.payload['device'] || options['device']
69
+            post_params['title'] = event.payload['title'] || event.payload['subject'] || options['title']
70
+            
71
+            url = (event.payload['url'] || options['url'] || '').to_s
72
+            url = url.slice 0..512
73
+            post_params['url'] = url
74
+            
75
+            url_title = (event.payload['url_title'] || options['url_title']).to_s
76
+            url_title = url_title.slice 0..100
77
+            post_params['url_title'] = url_title
78
+            
79
+            post_params['priority'] = (event.payload['priority'] || options['priority']).to_i
80
+            
81
+            if event.payload.has_key? 'timestamp'
82
+              post_params['timestamp'] = (event.payload['timestamp']).to_s
80 83
             end
81 84
 
82
-            if event.payload['priority'] || options['priority']
83
-              post_params['priority'] = (event.payload['priority'] || options['priority']).to_i
84
-            end
85
+            post_params['sound'] = (event.payload['sound'] || options['sound']).to_s
85 86
 
86
-            if event.payload['timestamp'] || options['timestamp']
87
-              post_params['timestamp'] = (event.payload['timestamp'] || options['timestamp']).to_s
88
-            end
87
+            post_params['retry'] = (event.payload['retry'] || options['retry']).to_i
89 88
 
90
-            if event.payload['sound'] || options['sound']
91
-              post_params['sound'] = (event.payload['sound'] || options['sound']).to_s
92
-            end
89
+            post_params['expire'] = (event.payload['expire'] || options['expire']).to_i
93 90
             
94
-            send_notification post_params
95
-          end
91
+            send_notification(post_params)
96 92
         end
97 93
       end
98 94
     end
@@ -102,7 +98,8 @@ module Agents
102 98
     end
103 99
 
104 100
     def send_notification(post_params)
105
-      
101
+      response = HTTParty.post(@@api_url, :query => post_params)
102
+      puts response
106 103
     end
107 104
 
108 105
   end

+ 201 - 0
spec/models/agents/pushover_agent_spec.rb

@@ -0,0 +1,201 @@
1
+require 'spec_helper'
2
+
3
+describe Agents::PushoverAgent do
4
+  before do
5
+    @checker = Agents::PushoverAgent.new(:name => 'Some Name',
6
+                                       :options => { :token => 'x',
7
+                                                :user => 'x',
8
+                                                :device => 'Some Device',
9
+                                                :title => 'Some Message Title',
10
+                                                :url => 'http://someurl.com',
11
+                                                :url_title => 'Some Url Title',
12
+                                                :priority => 0,
13
+                                                :timestamp => 'false',
14
+                                                :sound => 'pushover',
15
+                                                :retry => 0,
16
+                                                :expire => 0,
17
+                                                :expected_receive_period_in_days => '1'})
18
+     
19
+    @checker.user = users(:bob)
20
+    @checker.save!
21
+
22
+    @event = Event.new
23
+    @event.agent = agents(:bob_weather_agent)
24
+    @event.payload = { :message => 'Looks like its going to rain' }
25
+    @event.save!
26
+
27
+    @sent_notifications = []
28
+    stub.any_instance_of(Agents::PushoverAgent).send_notification  { |notification| @sent_notifications << notification}
29
+  end
30
+
31
+  describe '#receive' do
32
+    it 'should make sure multiple events are being received' do
33
+      event1 = Event.new
34
+      event1.agent = agents(:bob_rain_notifier_agent)
35
+      event1.payload = { :message => 'Some message' }
36
+      event1.save!
37
+
38
+      event2 = Event.new
39
+      event2.agent = agents(:bob_weather_agent)
40
+      event2.payload = { :message => 'Some other message' }
41
+      event2.save!
42
+
43
+      @checker.receive([@event,event1,event2])
44
+      @sent_notifications[0]['message'].should == 'Looks like its going to rain'
45
+      @sent_notifications[1]['message'].should == 'Some message'
46
+      @sent_notifications[2]['message'].should == 'Some other message'
47
+    end
48
+
49
+    it 'should make sure event title overrides default title' do
50
+      event = Event.new
51
+      event.agent = agents(:bob_rain_notifier_agent)
52
+      event.payload = { :message => 'Some message', :title => 'Some new title' }
53
+      event.save!
54
+
55
+      @checker.receive([event])
56
+      @sent_notifications[0]['title'].should == 'Some new title'
57
+    end
58
+
59
+    it 'should make sure event url overrides default url' do
60
+      event = Event.new
61
+      event.agent = agents(:bob_rain_notifier_agent)
62
+      event.payload = { :message => 'Some message', :url => 'Some new url' }
63
+      event.save!
64
+
65
+      @checker.receive([event])
66
+      @sent_notifications[0]['url'].should == 'Some new url'
67
+    end
68
+
69
+    it 'should make sure event url_title overrides default url_title' do
70
+      event = Event.new
71
+      event.agent = agents(:bob_rain_notifier_agent)
72
+      event.payload = { :message => 'Some message', :url_title => 'Some new url_title' }
73
+      event.save!
74
+
75
+      @checker.receive([event])
76
+      @sent_notifications[0]['url_title'].should == 'Some new url_title'
77
+    end
78
+
79
+    it 'should make sure event priority overrides default priority' do
80
+      event = Event.new
81
+      event.agent = agents(:bob_rain_notifier_agent)
82
+      event.payload = { :message => 'Some message', :priority => 1 }
83
+      event.save!
84
+
85
+      @checker.receive([event])
86
+      @sent_notifications[0]['priority'].should == 1
87
+    end
88
+
89
+    it 'should make sure event timestamp overrides default timestamp' do
90
+      event = Event.new
91
+      event.agent = agents(:bob_rain_notifier_agent)
92
+      event.payload = { :message => 'Some message', :timestamp => 'false' }
93
+      event.save!
94
+
95
+      @checker.receive([event])
96
+      @sent_notifications[0]['timestamp'].should == 'false'
97
+    end
98
+
99
+    it 'should make sure event sound overrides default sound' do
100
+      event = Event.new
101
+      event.agent = agents(:bob_rain_notifier_agent)
102
+      event.payload = { :message => 'Some message', :sound => 'Some new sound' }
103
+      event.save!
104
+
105
+      @checker.receive([event])
106
+      @sent_notifications[0]['sound'].should == 'Some new sound'
107
+    end
108
+
109
+    it 'should make sure event retry overrides default retry' do
110
+      event = Event.new
111
+      event.agent = agents(:bob_rain_notifier_agent)
112
+      event.payload = { :message => 'Some message', :retry => 1 }
113
+      event.save!
114
+
115
+      @checker.receive([event])
116
+      @sent_notifications[0]['retry'].should == 1
117
+    end
118
+
119
+    it 'should make sure event expire overrides default expire' do
120
+      event = Event.new
121
+      event.agent = agents(:bob_rain_notifier_agent)
122
+      event.payload = { :message => 'Some message', :expire => 60 }
123
+      event.save!
124
+
125
+      @checker.receive([event])
126
+      @sent_notifications[0]['expire'].should == 60
127
+    end
128
+  end
129
+
130
+  describe '#working?' do
131
+    it 'checks if events have been received within the expected receive period' do
132
+      # No events received
133
+      @checker.should_not be_working 
134
+      Agents::PushoverAgent.async_receive @checker.id, [@event.id]
135
+
136
+      # Just received events
137
+      @checker.reload.should be_working 
138
+      two_days_from_now = 2.days.from_now
139
+      stub(Time).now { two_days_from_now }
140
+      
141
+      # More time has passed than the expected receive period without any new events
142
+      @checker.reload.should_not be_working 
143
+    end
144
+  end
145
+
146
+  describe "validation" do
147
+    before do
148
+      @checker.should be_valid
149
+    end
150
+
151
+    it "should validate presence of token" do
152
+      @checker.options[:token] = ""
153
+      @checker.should_not be_valid
154
+    end
155
+
156
+    it "should validate presence of user" do
157
+      @checker.options[:user] = ""
158
+      @checker.should_not be_valid
159
+    end
160
+
161
+    it "should validate presence of expected_receive_period_in_days" do
162
+      @checker.options[:expected_receive_period_in_days] = ""
163
+      @checker.should_not be_valid
164
+    end
165
+
166
+    it "should make sure device is optional" do
167
+      @checker.options[:device] = ""
168
+      @checker.should be_valid
169
+    end
170
+
171
+    it "should make sure title is optional" do
172
+      @checker.options[:title] = ""
173
+      @checker.should be_valid
174
+    end
175
+
176
+    it "should make sure url is optional" do
177
+      @checker.options[:url] = ""
178
+      @checker.should be_valid
179
+    end
180
+
181
+    it "should make sure url_title is optional" do
182
+      @checker.options[:url_title] = ""
183
+      @checker.should be_valid
184
+    end
185
+
186
+    it "should make sure priority is optional" do
187
+      @checker.options[:priority] = ""
188
+      @checker.should be_valid
189
+    end
190
+
191
+    it "should make sure timestamp is optional" do
192
+      @checker.options[:timestamp] = ""
193
+      @checker.should be_valid
194
+    end
195
+
196
+    it "should make sure sound is optional" do
197
+      @checker.options[:sound] = ""
198
+      @checker.should be_valid
199
+    end
200
+  end
201
+end